/*
 * Copyright (C) 2010 M. Hautle.
 * 
 * This file is part of SimpleEL.
 * 
 * SimpleEL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * SimpleEL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with SimpleEL. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.simpleel.util;

import java.util.*;

/**
 * Hooks for {@link BeanCloner}.<br>
 * You may perform additional tasks for each cloned component using this hook.
 * 
 * @author M. Hautle
 */
public interface IBeanCloneHook {
    /** Instance representing null. May be returned by any <code>clone*</code> method if they would like to use <code>null</code> as cloned value. */
    public static final Object NULL_VALUE = new Object();

    /**
     * Hook called after a bean was cloned.
     * 
     * @param src The source bean
     * @param clone The cloned bean
     */
    void postBeanClone(Object src, Object clone);

    /**
     * Hook called after a list was cloned.
     * 
     * @param src The source list
     * @param clone The cloned list
     */
    void postListClone(List src, List clone);

    /**
     * Hook called after a set was cloned.
     * 
     * @param src The source set
     * @param clone The cloned set
     */
    void postSetClone(Set src, Set clone);

    /**
     * Hook called after a map was cloned.
     * 
     * @param src The source map
     * @param clone The cloned map
     */
    void postMapClone(Map src, Map clone);

    /**
     * Hook called after a array was cloned.
     * 
     * @param src The source array
     * @param clone The cloned array
     */
    void postArrayClone(Object[] src, Object[] clone);

    /**
     * Hook called before a bean gets cloned.<br>
     * Use it to replace source objects or to preinitialize proxies.
     * 
     * @param src The source bean
     * @return The object to clone
     */
    Object preBeanClone(Object src);

    /**
     * Hook called before a list gets cloned.<br>
     * Use it to replace source lists or to preinitialize proxies.
     * 
     * @param src The source list
     * @return The list to clone
     */
    List preListClone(List src);

    /**
     * Hook called before a set gets cloned.<br>
     * Use it to replace source sets or to preinitialize proxies.
     * 
     * @param src The source set
     * @return The set to clone
     */
    Set preSetClone(Set src);

    /**
     * Hook called before a map gets cloned.<br>
     * Use it to replace source maps or to preinitialize proxies.
     * 
     * @param src The source map
     * @return The map to clone
     */
    Map preMapClone(Map src);

    /**
     * Hook called before a array gets cloned.<br>
     * Use it to replace source arrays or to preinitialize proxies.
     * 
     * @param src The source array
     * @return The array to clone
     */
    Object[] preArrayClone(Object[] src);

    /**
     * Hook for replacing the default cloning behavior for a bean. It will be called after {@link #preBeanClone(Object)}.<br>
     * Use it to replace the default cloning procedure through a special one.
     * 
     * @param src The source bean
     * @return The value to use as clone, {@link #NULL_VALUE} for null, or null if the normal cloning procedure should be executed
     */
    Object cloneBean(Object src);

    /**
     * Hook for replacing the default cloning behavior for a {@link List}. It will be called after {@link #preListClone(List)}.<br>
     * Use it to replace the default cloning procedure through a special one.
     * 
     * @param src The source list
     * @return The list to use as clone, {@link #NULL_VALUE} for null, or null if the normal cloning procedure should be executed
     */
    List cloneList(List src);

    /**
     * Hook for replacing the default cloning behavior for a {@link Set}. It will be called after {@link #preSetClone(Set)}.<br>
     * Use it to replace the default cloning procedure through a special one.
     * 
     * @param src The source set
     * @return The set to use as clone, {@link #NULL_VALUE} for null, or null if the normal cloning procedure should be executed
     */
    Set cloneSet(Set src);

    /**
     * Hook for replacing the default cloning behavior for a {@link Map}. It will be called after {@link #preMapClone(Map)}.<br>
     * Use it to replace the default cloning procedure through a special one.
     * 
     * @param src The source map
     * @return The map to use as clone, {@link #NULL_VALUE} for null, or null if the normal cloning procedure should be executed
     */
    Map cloneMap(Map src);

    /**
     * Hook for replacing the default cloning behavior for a array. It will be called after {@link #preArrayClone(Object[])}.<br>
     * Use it to replace the default cloning procedure through a special one.
     * 
     * @param src The source array
     * @return The array to use as clone, {@link #NULL_VALUE} for null, or null if the normal cloning procedure should be executed
     */
    Object[] cloneArray(Object[] src);

    /**
     * Returns the type to instantiate for the given object.<br>
     * You may use this if you try to clone proxies.
     * 
     * @param src The source object
     * @return The type of the object (has to be the same type as src or a super type!)
     */
    Class<?> getType(Object src);
}
